package org.xbill.DNS;

import java.io.IOException;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.Iterator;
import java.util.List;

public class SimpleResolver
  implements Resolver
{
  public static final int DEFAULT_EDNS_PAYLOADSIZE = 1280;
  public static final int DEFAULT_PORT = 53;
  private static final short DEFAULT_UDPSIZE = 512;
  private static String defaultResolver = "localhost";
  private static int uniqueID = 0;
  private InetSocketAddress address;
  private boolean ignoreTruncation;
  private InetSocketAddress localAddress;
  private OPTRecord queryOPT;
  private long timeoutValue;
  private TSIG tsig;
  private boolean useTCP;

  public SimpleResolver()
    throws UnknownHostException
  {
    this(null);
  }

  public SimpleResolver(String paramString)
    throws UnknownHostException
  {
    this.timeoutValue = 10000L;
    if (paramString == null)
    {
      paramString = ResolverConfig.getCurrentConfig().server();
      if (paramString == null)
        paramString = defaultResolver;
    }
    if (paramString.equals("0"))
      localInetAddress = InetAddress.getLocalHost();
    while (true)
    {
      this.address = new InetSocketAddress(localInetAddress, 53);
      return;
      localInetAddress = InetAddress.getByName(paramString);
    }
  }

  private void applyEDNS(Message paramMessage)
  {
    if ((this.queryOPT == null) || (paramMessage.getOPT() != null));
    while (true)
    {
      return;
      paramMessage.addRecord(this.queryOPT, 3);
    }
  }

  private int maxUDPSize(Message paramMessage)
  {
    int i;
    OPTRecord localOPTRecord = paramMessage.getOPT();
    if (localOPTRecord == null)
      i = 512;
    while (true)
    {
      return i;
      i = localOPTRecord.getPayloadSize();
    }
  }

  private Message parseMessage(byte[] paramArrayOfByte)
    throws WireParseException
  {
    Message localMessage;
    try
    {
      localMessage = new Message(paramArrayOfByte);
      return localMessage;
    }
    catch (IOException localIOException)
    {
      Object localObject = localIOException;
      if (Options.check("verbose"))
        ((IOException)localObject).printStackTrace();
      if (!(localObject instanceof WireParseException))
        localObject = new WireParseException("Error parsing message");
      throw ((WireParseException)localObject);
    }
  }

  private Message sendAXFR(Message paramMessage)
    throws IOException
  {
    ZoneTransferIn localZoneTransferIn = ZoneTransferIn.newAXFR(paramMessage.getQuestion().getName(), this.address, this.tsig);
    localZoneTransferIn.setTimeout((int)(getTimeout() / 1000L));
    localZoneTransferIn.setLocalAddress(this.localAddress);
    while (true)
    {
      Message localMessage;
      Iterator localIterator;
      try
      {
        localZoneTransferIn.run();
        List localList = localZoneTransferIn.getAXFR();
        localMessage = new Message(paramMessage.getHeader().getID());
        localMessage.getHeader().setFlag(5);
        localMessage.getHeader().setFlag(0);
        localMessage.addRecord(paramMessage.getQuestion(), 0);
        localIterator = localList.iterator();
        if (!(localIterator.hasNext()))
          return localMessage;
      }
      catch (ZoneTransferException localZoneTransferException)
      {
        throw new WireParseException(localZoneTransferException.getMessage());
      }
      localMessage.addRecord((Record)localIterator.next(), 1);
    }
  }

  public static void setDefaultResolver(String paramString)
  {
    defaultResolver = paramString;
  }

  private void verifyTSIG(Message paramMessage1, Message paramMessage2, byte[] paramArrayOfByte, TSIG paramTSIG)
  {
    if (paramTSIG == null);
    while (true)
    {
      int i;
      do
      {
        return;
        i = paramTSIG.verify(paramMessage2, paramArrayOfByte, paramMessage1.getTSIG());
      }
      while (!(Options.check("verbose")));
      System.err.println("TSIG verify: " + Rcode.string(i));
    }
  }

  InetSocketAddress getAddress()
  {
    return this.address;
  }

  TSIG getTSIGKey()
  {
    return this.tsig;
  }

  long getTimeout()
  {
    return this.timeoutValue;
  }

  public Message send(Message paramMessage)
    throws IOException
  {
    Object localObject;
    if (Options.check("verbose"))
      System.err.println("Sending to " + this.address.getAddress().getHostAddress() + ":" + this.address.getPort());
    if (paramMessage.getHeader().getOpcode() == 0)
    {
      Record localRecord = paramMessage.getQuestion();
      if ((localRecord != null) && (localRecord.getType() == 252))
        localObject = sendAXFR(paramMessage);
    }
    while (true)
    {
      label336: Message localMessage2;
      return localObject;
      Message localMessage1 = (Message)paramMessage.clone();
      applyEDNS(localMessage1);
      if (this.tsig != null)
        this.tsig.apply(localMessage1, null);
      byte[] arrayOfByte1 = localMessage1.toWire(65535);
      int i = maxUDPSize(localMessage1);
      int j = 0;
      long l = System.currentTimeMillis() + this.timeoutValue;
      while (true)
      {
        byte[] arrayOfByte2;
        while (true)
        {
          String str;
          do
          {
            if ((this.useTCP) || (arrayOfByte1.length > i))
              j = 1;
            if (j != 0);
            for (arrayOfByte2 = TCPClient.sendrecv(this.localAddress, this.address, arrayOfByte1, l); arrayOfByte2.length < 12; arrayOfByte2 = UDPClient.sendrecv(this.localAddress, this.address, arrayOfByte1, i, l))
              throw new WireParseException("invalid DNS header - too short");
            int k = ((0xFF & arrayOfByte2[0]) << 8) + (0xFF & arrayOfByte2[1]);
            int i1 = localMessage1.getHeader().getID();
            if (k == i1)
              break label336;
            str = "invalid message id: expected " + i1 + "; got id " + k;
            if (j != 0)
              throw new WireParseException(str);
          }
          while (!(Options.check("verbose")));
          System.err.println(str);
        }
        localMessage2 = parseMessage(arrayOfByte2);
        verifyTSIG(localMessage1, localMessage2, arrayOfByte2, this.tsig);
        if ((j != 0) || (this.ignoreTruncation) || (!(localMessage2.getHeader().getFlag(6))))
          break;
        j = 1;
      }
      localObject = localMessage2;
    }
  }

  public Object sendAsync(Message paramMessage, ResolverListener paramResolverListener)
  {
    String str1;
    monitorenter;
    try
    {
      int i = uniqueID;
      uniqueID = i + 1;
      Integer localInteger = new Integer(i);
      monitorexit;
      Record localRecord = paramMessage.getQuestion();
      if (localRecord != null)
      {
        ResolveThread localResolveThread;
        str1 = localRecord.getName().toString();
        String str2 = super.getClass() + ": " + str1;
        return localInteger;
      }
    }
    finally
    {
      while (true)
      {
        monitorexit;
        throw localObject;
        str1 = "(none)";
      }
    }
  }

  public void setAddress(InetAddress paramInetAddress)
  {
    this.address = new InetSocketAddress(paramInetAddress, this.address.getPort());
  }

  public void setAddress(InetSocketAddress paramInetSocketAddress)
  {
    this.address = paramInetSocketAddress;
  }

  public void setEDNS(int paramInt)
  {
    setEDNS(paramInt, 0, 0, null);
  }

  public void setEDNS(int paramInt1, int paramInt2, int paramInt3, List paramList)
  {
    if ((paramInt1 != 0) && (paramInt1 != -1))
      throw new IllegalArgumentException("invalid EDNS level - must be 0 or -1");
    if (paramInt2 == 0)
      paramInt2 = 1280;
    this.queryOPT = new OPTRecord(paramInt2, 0, paramInt1, paramInt3, paramList);
  }

  public void setIgnoreTruncation(boolean paramBoolean)
  {
    this.ignoreTruncation = paramBoolean;
  }

  public void setLocalAddress(InetAddress paramInetAddress)
  {
    this.localAddress = new InetSocketAddress(paramInetAddress, 0);
  }

  public void setLocalAddress(InetSocketAddress paramInetSocketAddress)
  {
    this.localAddress = paramInetSocketAddress;
  }

  public void setPort(int paramInt)
  {
    this.address = new InetSocketAddress(this.address.getAddress(), paramInt);
  }

  public void setTCP(boolean paramBoolean)
  {
    this.useTCP = paramBoolean;
  }

  public void setTSIGKey(TSIG paramTSIG)
  {
    this.tsig = paramTSIG;
  }

  public void setTimeout(int paramInt)
  {
    setTimeout(paramInt, 0);
  }

  public void setTimeout(int paramInt1, int paramInt2)
  {
    this.timeoutValue = (1000L * paramInt1 + paramInt2);
  }
}